#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <pthread.h>
#include <ncurses.h>
#include <signal.h>
#include <unistd.h>
#include "../Headers/crazy.h"
#include "../Headers/shared.h"
#include "../Headers/winbufADT.h"
#include "../Headers/msgqueue.h"

#define CANT_COMM 6
#define MAX_COMM_LEN 255
#define MAX_MSG_SIZE 255
#define MAX_NAME_LEN 20
#define TIMEOUT 60

typedef struct threadParamT{
    char type[TYPE_LEN+1];
    crazyADT crazy;
}threadParamT;


/* ------------------------------------------------------------------------- */
/* ---------------------- Variables Globales ------------------------------- */
/* ------------------------------------------------------------------------- */

/* Estructura generica que incluye todas las demas estructuras de tipo host */
genHostT g_host;

/* Variable donde el thread q escucha deja los mensajes */
char server_msg[USER_NAME_LEN + MAX_MSG_SIZE];

int g_flag = 0;

/* Flag que se setea cuando recibo SIGINT */
int int_flag = 0;
/* Flag qindica q estoy recibiendo un comando */
int comm_flag = 1;

/* Flag q indica si estoy en modo comando por defecto */
int comm_mode = 1;

/* Flag que indica si ya ingrese a una sesion */
int chating = 0;

/* Flag que indica si ya tiene un nombre de usuario asignado */
int has_name = 0;

/* Lo uso para matar el thread */
pthread_t thread_id;

/* Flag que me indica si tengo algo para leer en shm */
int shm_flag = 0;

/* Flag que indica si llego una senial para las funciones listenXXX */
int usr_interrupt = 0;

/* Flag que indica si debo refrescar la lista de usuarios conectados */
int alarm_f = 0;

/* String que indica en q sesion me encuentro */
char g_session[MAX_MSG_SIZE];

/* Flag que indica si debo desconectarme */
int disconnect_f = 0;

/* String que se envia al servidor */
char complete_msg[USER_NAME_LEN + MAX_MSG_SIZE + 2] = {0};
int name_len = 1; /* por el 1 q indica q es un mensaje */

/* Thread que se encarga de escuchar mensajes que provienen del sevidor */
pthread_t thread;
/* Variable mutex para comunicacion entre threads */
pthread_mutex_t mymutex;

/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */

void * listenServer (void * type);

void listenTCPOrFIFOServer (void * params);

void listenMSGQServer (void * params);

void listenSHMServer (void * params);

int cursesClient (crazyADT crazy, char * type);

/* ------------------------------------------------------------------------- */
/* ------------------------ Funciones de Uso ------------------------------- */
/* ------------------------------------------------------------------------- */

void getUserName (char * usern_name);

int initSession (crazyADT crazy, winbufADT wb, char * server_ans);

void listSessions (crazyADT crazy, winbufADT wb, char * server_ans);

void listSessionUsers (crazyADT crazy, winbufADT wb, char * server_ans);

/* ------------------------------------------------------------------------- */
/* -------------------- Funciones Auxiliares ------------------------------- */
/* ------------------------------------------------------------------------- */

void comm_handler (int sig);

void shm_handler (int sig);

void alarm_handler (int sig);

void listen_continue (int sig);

void pipe_handler (int sig);

int getServerInfo (char * type);

int getServerInfoTCP (void);

int getServerInfoFIFO (void);

int getServerInfoSHM (void);

void fillUsersWin (winbufADT wb, char * server_ans);

void refreshUsersWin (crazyADT crazy, char * room_name);

threadParamT * createThreadParam (crazyADT crazy, char * type);

void createThread (crazyADT crazy, char * type);

int callCommand (char * command, char * type, winbufADT wb, crazyADT crazy, char * room_name);


/* ------------------------------------------------------------------------- */
/* ------------------------ -- Main ---------------------------------------- */
/* ------------------------------------------------------------------------- */

int
main(int argc, char * argv[])
{
    crazyADT crazy;

    (void) signal(SIGPIPE, pipe_handler);
        
    /* Valido argumentos recibidos por linea de comandos */
    if (!validArgs (argc, argv[1]))
        return 1;

    /* Espero nformacion sobre el servidor y usuario antes de conectarme */
    getServerInfo (argv[1]);
    
    /* Inicio conexion */
    if ((crazy = open_conn (g_host, argv[1])) == NULL){
        fprintf (stdout, "Error: Could not initialize connection\n");
        return 1;
    }
	
    while (cursesClient (crazy, argv[1]) == 1){
    	/* reseteo variables globales */
        g_flag = 0;
        int_flag = 0;
        comm_flag = 1;
        comm_mode = 1;
        chating = 0;
        shm_flag = 0;  
        usr_interrupt = 0; 
        alarm_f = 0;
        disconnect_f = 0;
    }
    
    (void) close_conn (crazy);

   return 0;

}

/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */

void *
listenServer (void * params)
{
    threadParamT * ptp = params;
    
    thread_id = pthread_self();
    
    if (!strncmp (ptp->type, "TCP", strlen ("TCP")))
        listenTCPOrFIFOServer (params);
    else if (!strncmp (ptp->type, "MSGQ", strlen ("MSGQ")))
        listenMSGQServer (params);
    else if (!strncmp (ptp->type, "FIFO", strlen ("FIFO")))
        listenTCPOrFIFOServer (params);
    else if (!strncmp (ptp->type, "SHM", strlen ("SHM")))
        listenSHMServer (params);
}   

void
listenTCPOrFIFOServer (void * params)
{
    threadParamT * ptp = params;
    int f, i = 0;
    char ch, buf[MAX_MSG_SIZE] = {0};
    struct timeval tv;
    char string[50], r_string[MSG_SIZE], send [MSG_SIZE] = {0};
    fd_set set, master;
    
    (void) signal (SIGUSR2, listen_continue);
    
    /* Solo me interumpe SIGUSR2 cuando me echo a dormir */
    sigset_t mask, oldmask; 
    sigfillset (&mask); 
    sigdelset (&mask, SIGUSR2);
    
    f = get_fd (ptp->crazy);
    
    FD_ZERO(&master);
    FD_SET(f, &master);

    while(ALWAYS){
        FD_SET(f, &master);
        /* Me quedo bloqueado esperando una conexion */
        if ( set = master, select( f +1, &set, NULL, NULL, NULL) > 0 ){
                if (FD_ISSET(f, &set))
                {
                    /* Recibo mensajes del servidor */
                    rcv_data(ptp->crazy, buf, MAX_MSG_SIZE);
                    
                    /* Tengo q escribir lo q recibi en la memoria compartida */
                    strcpy (server_msg, buf);
                    g_flag = 1;
                    
                    /* Aca me echo a dormir hasta q me depsierten */
                    sigprocmask (SIG_BLOCK, &mask, &oldmask);
                    while (!usr_interrupt)
                        sigsuspend (&oldmask);
                    sigprocmask (SIG_UNBLOCK, &mask, NULL);
                    
                    usr_interrupt = 0;
                    
                    /* Reseteo el string */
                    putZeros (buf, MAX_MSG_SIZE);
                }
        }
    }
}    

void
listenMSGQServer (void * params)
{
    int fd;
    struct q_entry q;
    threadParamT * ptp = params;  
    
    (void) signal (SIGUSR2, listen_continue);

    sigset_t mask, oldmask;
    sigfillset (&mask); 
    sigdelset (&mask, SIGUSR2);
    
    fd = get_fd (ptp->crazy);
    
    while (ALWAYS){
        /* Me quedo bloqueado esperando q me llegue un mensaje */
        msgrcv (fd, &q, MAX_MSG_SIZE, getpid(), 0);
                    
        /* Tengo q escribir lo q recibi en la memoria compartida */
        strcpy (server_msg, q.text);
        g_flag = 1;
                    

                    
        /* Aca me echo a dormir hasta q me depsierten */
        sigprocmask (SIG_BLOCK, &mask, &oldmask);
        while (!usr_interrupt)
            sigsuspend (&oldmask);
        sigprocmask (SIG_UNBLOCK, &mask, NULL);
        
        usr_interrupt = 0;
                    
        /* Reseteo el string */
        putZeros (q.text, MAX_MSG_SIZE);
    }
}

void
listenSHMServer (void * params)
{
    char buf[MAX_MSG_SIZE] = {0};
    threadParamT * ptp = params;
    
    (void) signal (SIGUSR1, shm_handler);
    (void) signal (SIGUSR2, listen_continue);
    
    while (ALWAYS)
    {
        
        /* Espero una senial desde el server q me dice q hay algo para leer */
        wait(NULL);
        if (shm_flag)
        {
            rcv_data(ptp->crazy, buf, MAX_MSG_SIZE);
            
            /* Tengo q escribir lo q recibi en la memoria compartida */
            strcpy (server_msg, buf);
            g_flag = 1;
                    
            while (g_flag == 1)
                sleep (1);
                    
            putZeros (buf, MAX_MSG_SIZE);
            shm_flag = 0;
            
        }
    }
    
    return ;
}

int
cursesClient (crazyADT crazy, char * type)
{
    int ch, size, state, timevar;
    int y, x;
    int startx, starty, width, height;
    char * line, c = 1;
    char * aux;
    char * prompt_cmmd = "cmmd>: ";
    char * prompt_chat = "chat>: ";
    char answer[100] = {0};
    char * quit_msg = "Salir";
    char command[MAX_COMM_LEN];
    char room_name[ROOM_NAME_LEN] = {0};
    winbufADT wb;

    timevar = time(NULL);

    /* Creo el thread que escucha mensajes del servidor */
    createThread (crazy, type);

    (void) signal(SIGINT, comm_handler);
    (void) signal (SIGALRM, alarm_handler);
    
    /* En cada mensaje se manda primero un 1 para indicar es q un mensaje
     * luego el nombre del usuario y luego ':' */
     complete_msg[0] = 1;

    alarm(30);
     
    (void) signal (SIGINT, comm_handler);
    
    wb = NewWB (MAX_MSG_SIZE - USER_NAME_LEN);
    
    putWBStr (wb, "cmmd>: ", PROMPT_WIN, NO_ENTER);
    
    while ((ch = getWBCh(wb)) != KEY_F(2))
    {
        /* Chequeo si se cayo el server */
        if (disconnect_f || (time(NULL) - timevar) > TIMEOUT){
            pthread_kill (thread_id, SIGINT);
            WBColorOn (wb, 1, MSGS_WIN);
            putWBStr (wb, "*** Imposible conectarse con el servidor, cerrando el programa...\n", MSGS_WIN, ENTER);
            WBColorOff (wb, 1, MSGS_WIN);  
            sleep (2);
            FreeWB (wb);
            return -1;
        }   
            
        /* Refresco la ventana con usuarios conectados */
        if (alarm_f){
            if (chating)
                refreshUsersWin (crazy, g_session);
            (void) signal (SIGALRM, alarm_handler);
            alarm (7);
            alarm_f = 0;
        }
        /* Me llego un SIGINT para ingresar un comando */
    	if (int_flag)
        {
        	/* Descarto cualquier cosa q estaba escribiendo */
        	line = getAndEraseWB (wb, &size);
        	//free (line);	
        	/* Cambio el prompt */
        	putWBStr (wb, "cmmd>: ", PROMPT_WIN, NO_ENTER);
        	int_flag = 0;
        	comm_flag = 1;
        }
    	else
    	{
    		if (ch == '\n'){
    			/* Era un comando */
    			if (comm_flag)
    			{
    				line = getAndEraseWB (wb, &size);
                    strcpy (complete_msg+name_len, line + strlen ("cmmd>: "));
    				state = callCommand (complete_msg+name_len, type, wb, crazy, room_name);
    				free (line);
    				/* Si el comando era 'Salir' */
                    if (state == -1)
                    {
                        if (chating){
                            /* Si estaba chateando cierro la sesion */
                            send_data (crazy, quit_msg, strlen (quit_msg));  
                            pthread_kill (thread_id, SIGINT);
                            WBColorOn (wb, 1, MSGS_WIN);
                            putWBStr (wb, "*** Se abandono la sesion\n", MSGS_WIN, ENTER);
                            WBColorOff (wb, 1, MSGS_WIN);                            
                            FreeWB (wb);
                    		return 1;
                    	}
                    	else{
                            FreeWB (wb);
                            return -1; 
                        }                   
                    }
    				/* Si estoy en modo chat vuelvo */
                    if (comm_mode == 0)
                    	comm_flag = 0;
                    putZeros (complete_msg+name_len, USER_NAME_LEN + MAX_MSG_SIZE + 2 - strlen (g_host.user_name) -2);
                    
                    if (!chating)
                        putWBStr (wb, "cmmd>: ", PROMPT_WIN, NO_ENTER);
                    else
                        putWBStr (wb, "chat>: ", PROMPT_WIN, NO_ENTER);
    			}
    			/* Era un mensaje */
    			else{
    				line = getAndEraseWB (wb, &size);
    				strcpy (complete_msg+name_len, line + strlen ("chat>: ")); 
    				send_data (crazy, complete_msg, strlen (g_host.user_name) + size + 2);
    				free (line);
    				putZeros (complete_msg+name_len, USER_NAME_LEN + MAX_MSG_SIZE + 2 - strlen (g_host.user_name) -2);
    				putWBStr (wb, "chat>: ", PROMPT_WIN, NO_ENTER);
    			}	
    		}
    		else if (ch != ERR){
    			putWBChar (wb, ch, PROMPT_WIN);
    		}
    		
    		/* Me fijo si me llego algo del server para imprimir */
    		if (g_flag == 1)
    		{
                /* Reseteo el timeout */
                timevar = time(NULL);
                
                /* Puede ser una respuesta a Refresh  */
                if (server_msg[0] == 1 && chating)
                    fillUsersWin (wb, server_msg+1);
                /* Puede ser una respuesta a Listar */
                else if (server_msg[0] == 1){
                        WBColorOn (wb, 2, MSGS_WIN);
                        putWBStr (wb, "*** Respuesta a 'Listar':", MSGS_WIN, ENTER);
                        putWBStr (wb, server_msg+1, MSGS_WIN, ENTER);
                        WBColorOff (wb, 2, MSGS_WIN);
                }
                /* Puede ser una respuesta a SEsiones */
                else if (server_msg[0] == 2){
                        WBColorOn (wb, 2, MSGS_WIN);
                        putWBStr (wb, "*** Respuesta a 'Sesiones':", MSGS_WIN, ENTER);
                        putWBStr (wb, server_msg+1, MSGS_WIN, ENTER);
                        WBColorOff (wb, 2, MSGS_WIN);
                }
                /* Puede ser una respuesta  a Ingresar */
                else if (server_msg[0] == 3){
                    if (!strncmp (server_msg+1, INIT_SUCCES, strlen (INIT_SUCCES)))
                    {
                        WBColorOn (wb, 2, MSGS_WIN);
                        putWBStr (wb, "*** Respuesta a 'Ingresar':\nSe ingreso a la sesion", MSGS_WIN, ENTER);
                        WBColorOff (wb, 2, MSGS_WIN);
                        refreshUsersWin (crazy, g_session);
                        line = getAndEraseWB (wb, &size);
                        //free (line);  
                        /* Cambio el prompt */
                        putWBStr (wb, "chat>: ", PROMPT_WIN, NO_ENTER);
                        chating = 1;
                        comm_flag = 0;
                        comm_mode = 0;
                    }  
                    else putWBStr (wb, "*** Respuesta a 'Ingresar':\nNo se pudo ingresar a la sesion", MSGS_WIN, ENTER);                  
                }
                /* Es un mensaje */
                else{
                    WBColorOn (wb, 3, MSGS_WIN);
    			    putWBStr (wb, server_msg, MSGS_WIN, ENTER);
                    WBColorOff (wb, 3, MSGS_WIN);                
                }
                pthread_kill (thread_id, SIGUSR2);
                g_flag = 0;                
    		}
    		
    	}
    }
    /* Cuando termina el ncurses */
    FreeWB (wb);
    
    return ;
}

/* ------------------------------------------------------------------------- */
/* ------------------------ Funciones de Uso ------------------------------- */
/* ------------------------------------------------------------------------- */

void
getUserName (char * user_name)
{
    /* sacar esto y preguntar nombre de usuario */
    /* no aceptar q tenga espacios en blanco */
    strcpy (g_host.user_name, user_name);
    
    strcpy (complete_msg + 1, user_name);
    *(complete_msg + 1 + strlen (user_name)) = ':';
    *(complete_msg + 1 + strlen (user_name) + 1) = ' ';
    
    name_len += strlen(user_name) + 1 + 1; 
    
    has_name = 1;
    
    return ;
}

int
initSession (crazyADT crazy, winbufADT wb, char * room_name)
{
    int f;
    char string[MAX_MSG_SIZE] = {0};
    char server_ans[MAX_MSG_SIZE] = {0};
    char aux[MAX_MSG_SIZE] = {0};
    
    /* Envio mensaje al servidor */
    /* Dejar q el usuario elija */
    sprintf (string, "Ingresar %s %s", room_name, g_host.user_name);
    send_data (crazy, string, strlen (string));
    
    return 0;
}

void
listSessions (crazyADT crazy, winbufADT wb, char * server_ans)
{
    int f;
    char string[MAX_MSG_SIZE] = {0};
    
    /* Envio mensaje al servidor */
    sprintf (string, "Sesiones");
    send_data (crazy, string, strlen ("Sesiones"));   
    
    return ;
}  

void
listSessionUsers (crazyADT crazy, winbufADT wb, char * room_name)
{
    int f;
    char string[MAX_MSG_SIZE] = {0};
    char aux[MAX_MSG_SIZE] = {0};
    
    strcpy (aux, room_name);
    
    /* Envio mensaje al servidor */
    sprintf (string, "Listar %s", aux);
    send_data (crazy, string, strlen (string));   
    
    return ;        
}


/* ------------------------------------------------------------------------- */
/* -------------------- Funciones Auxiliares ------------------------------- */
/* ------------------------------------------------------------------------- */

void
comm_handler (int sig)
{
    if (!comm_mode && !comm_flag)
	   int_flag = 1;
}


void 
shm_handler (int sig)
{
    shm_flag = 1;
}

void
alarm_handler (int sig)
{
    
    alarm_f = 1;
}

void
listen_continue (int sig)
{
    usr_interrupt = 1;
}

void 
pipe_handler (int sig)
{
    disconnect_f = 1;
}

int 
getServerInfo (char * type)
{
    
    if (!strncmp (type, "TCP", strlen ("TCP"))){
        return getServerInfoTCP ();
    }
    else if (!strncmp (type, "MSGQ", strlen ("MSGQ"))){
        return getServerInfoMSGQ ();
    }
    else if (!strncmp (type, "FIFO", strlen ("FIFO"))){
        return getServerInfoFIFO ();
    }
    else if (!strncmp (type, "SHM", strlen ("SHM"))){
        return getServerInfoSHM ();
    }
}

/* debe preguntarle al usuario  y validar */
int
getServerInfoTCP (void)
{
    strcpy (g_host.host_dir, TCP_HOST);
    strcpy (g_host.service, TCP_PORT);

    return 1;
}    

int
getServerInfoMSGQ (void)
{
    g_host.q_key = Q_KEY;
    return 1;
}  

int
getServerInfoFIFO (void)
{
	strcpy (g_host.fifo_name, FIFO_INIT);
	return 1;
}

int
getServerInfoSHM (void)
{
    g_host.shm_id = SHM_INIT;
    g_host.sem_id = SEM_INIT;
    return 1;   
}

void
refreshUsersWin (crazyADT crazy, char * room_name)
{
    char string[MAX_MSG_SIZE] = {0};
    char aux[MAX_MSG_SIZE] = {0};
    
    strcpy (aux, room_name);
    
    /* Envio mensaje al servidor */
    sprintf (string, "Listar %s", aux);
    send_data (crazy, string, strlen (string));  
}

void
fillUsersWin (winbufADT wb, char * server_ans)
{
    int i;
    char aux[MAX_MSG_SIZE] = {0};
    int j = 0;
    
    WBRowRest (wb);
    
    if (strcmp (server_ans, "No hay ningun usuario conectado a ese chatroom") == 0)
        return ;
    
    /* Si al final hay un \n es un nombre de usuario */
    for (i=0 ; server_ans[i] != '\0' ; i++)
    {
        if (server_ans[i] != '\n')
            aux[i] = server_ans[i];
        else
        {
            aux[i] = '\0';
            WBColorOn (wb, 4, USERS_WIN);
            putWBStr (wb, aux+j, USERS_WIN, ENTER);
            WBColorOff (wb, 4, USERS_WIN);
            j = i + 1;
        }
    }
    WBColorOn (wb, 4, USERS_WIN);
    putWBStr (wb, aux+j, USERS_WIN, ENTER);
    WBColorOff (wb, 4, USERS_WIN);
    aux[i] = '\0';
    
    return ;
}

threadParamT *
createThreadParam (crazyADT crazy, char * type)
{
    threadParamT * ptp;
    
    if ((ptp = malloc (sizeof (struct threadParamT))) == NULL){
        fprintf (stdout, "Unknowk error\n");
        return NULL;
    }
    
    ptp->crazy = crazy;
    strcpy (ptp->type, type);
    
    return ptp;
}

void
createThread (crazyADT crazy, char * type)
{
    int rc;
    threadParamT * ptp;
    pthread_attr_t attr;       
    /* Creo una struct con los parametros que recibe el thread */
    ptp = createThreadParam (crazy, type);
    
    /* inicializo la variable mutex */
    pthread_mutex_init(&mymutex, NULL);
    
    /* Por default empieza lockeada */
    //pthread_mutex_unlock (mymutex);

    /* Creo un thread que se encarga de escuchar mensajes 
     * que lleguen desde el servidor */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    /* Defino un tamanio de stack ? */
    rc = pthread_create (&thread, NULL, listenServer, (void *) ptp); 
    if (rc){
        perror ("Error: Unknown thread creation problem\n");
        pthread_mutex_destroy(&mymutex);
        exit(-1);
    }
    pthread_attr_destroy(&attr);

    /* Libero memoria */            
    pthread_mutex_destroy(&mymutex);
    //pthread_exit(NULL);
}

int
callCommand (char * command, char * type, winbufADT wb, crazyADT crazy, char * room_name)
{
    int CantComm = CANT_COMM;
    char server_ans[MAX_MSG_SIZE] = {0};
    int i;
    char * commands[] = {"Help", "Usuario-", "Sesiones", "Listar-", "Ingresar-", "Salir"};
	
    for (i=0; i<=CantComm; i++){
        if (i == CantComm){
            WBColorOn (wb, 1, MSGS_WIN);
        	putWBStr (wb, "*** El comando ingresado es invalido", MSGS_WIN, ENTER);
            WBColorOff (wb, 1, MSGS_WIN);
            return 1;
        }
        if(i >= 0 && !strncmp(commands[i], command, strlen (commands[i]))){
            if (i == 0){
                putWBStr (wb, "*** Comandos:\n***  Usuario-USER_NAME\n***  Sesiones\n***  Listar-SESSION_NAME\n***  Ingresar-SESSION_NAME\n***  Salir\n", MSGS_WIN, ENTER);
                return 1;
            }
            else if (i == 1){
            	if (chating){
                    WBColorOn (wb, 1, MSGS_WIN);
            		putWBStr (wb, "*** No se puede cambiar el nombre de usuario una vez que se ingreso a una sesion\n", MSGS_WIN, ENTER);
                    WBColorOff (wb, 1, MSGS_WIN);
                }
                else{
                	if (strlen (command + strlen ("Usuario-")) > MAX_NAME_LEN - 1)
                	{
                        WBColorOn (wb, 1, MSGS_WIN);
                		putWBStr (wb, "*** EL nombre de usuario es demasiado largo (Max. 19 caracteres)\n", MSGS_WIN, ENTER);
                        WBColorOff (wb, 1, MSGS_WIN);                		
                	}
                	else{
                		getUserName (command + strlen ("Usuario-"));
                		WBColorOn (wb, 2, MSGS_WIN);
                		putWBStr (wb, "*** Su nombre de usuario es ahora: ", MSGS_WIN, NO_ENTER);
                		putWBStr (wb, g_host.user_name, MSGS_WIN, ENTER);
                		WBColorOff (wb, 2, MSGS_WIN);
                	}
                }
                return 1;
            }
            else if (i == 2){
                listSessions (crazy, wb, server_ans);
                putZeros (server_ans, MAX_MSG_SIZE);
                return 1;
            }
            else if (i == 3){
                listSessionUsers (crazy, wb, command + strlen ("Listar-"));
                return 1;                
            }
            else if (i == 4){
            	if (chating){
                    WBColorOn (wb, 1, MSGS_WIN);
            		putWBStr (wb, "*** Respuesta a 'Ingresar':\nPara ingresar a otra sesion primero debe salir de la actual\n", MSGS_WIN, ENTER);
                    WBColorOff (wb, 1, MSGS_WIN);
                }
                else if (!has_name){
                    WBColorOn (wb, 1, MSGS_WIN);
                    putWBStr (wb, "*** Respuesta a 'Ingresar':\nDebe tener un nombre de usuario para ingresar a una sesion\n", MSGS_WIN, ENTER);
            	   WBColorOff (wb, 1, MSGS_WIN);
                }
                else{
                        initSession (crazy, wb, command + strlen ("Ingresar-"));
                        putZeros (g_session, MAX_MSG_SIZE);
                        strcpy (g_session, command + strlen ("Ingresar-"));
                        return 2;
                    
                }
                return 1;
            }
            else if (i == 5)
                return -1;          
        }
            
    }
    return 1;
}
